﻿using litsdk;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;

namespace litqrcode
{
    [litsdk.ActivityInfo(Name = "二维码识别生成",RefFile = "zxing.dll,zxing.presentation.dll")]
    public class QrCodeActivity : litsdk.ProcessActivity
    {
        static QrCodeActivity()
        {
        }

        public override string Name { get; set; } = "二维码识别生成";

        public override ActivityGroup Group => ActivityGroup.AI;

        /// <summary>
        /// 是否生成
        /// </summary>
        public bool IsCreate = true;

        /// <summary>
        /// 生成或识别内容
        /// </summary>
        public string Content = "";

        /// <summary>
        /// 保存变量
        /// </summary>
        public string SaveVarName = "";

        /// <summary>
        /// 图片大小
        /// </summary>
        public int ImgSize = 258;

        /// <summary>
        /// 容错率真7%
        /// </summary>
        public int ErrorCorrectionLevel = 0;

        /// <summary>
        /// https://www.cnblogs.com/huanyun/p/11698424.html
        /// https://www.cnblogs.com/mohanchen/p/7086902.html
        /// </summary>
        /// <param name="context"></param>
        public override void Execute(ActivityContext context)
        {
            Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>();
            hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.Add(EncodeHintType.MARGIN, 1);

            switch (ErrorCorrectionLevel)
            {
                case 0:
                    hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.L);
                    break;
                case 1:
                    hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.M);
                    break;
                case 2:
                    hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.Q);
                    break;
                case 3:
                    hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H);
                    break;
            }
            if (this.IsCreate)
            {
                string content = context.ReplaceVar(this.Content);
                QRCodeWriter writer = new QRCodeWriter();
                BitMatrix matrix = writer.encode(content, BarcodeFormat.QR_CODE, this.ImgSize, this.ImgSize, hints);
                Bitmap m = toBitmap(matrix);
                string save = context.GetStr(this.SaveVarName);
                m.Save(save, System.Drawing.Imaging.ImageFormat.Jpeg);
                context.WriteLog($"生成二维码成功，图片边长{m.Width}");
            }
            else
            {
                string imgfile = context.ReplaceVar(this.Content);
                if (!System.IO.File.Exists(imgfile)) throw new Exception("二维码图片不存在");
                Image image = System.Drawing.Image.FromFile(imgfile);
                Bitmap barcodeBitmap = new Bitmap(image);
                BarcodeReader reader = new BarcodeReader();

                reader.Options.CharacterSet = "UTF-8";

                var result = reader.Decode(barcodeBitmap);

                context.SetVarStr(this.SaveVarName, "");
                if (result != null)
                {
                    context.SetVarStr(this.SaveVarName, result.Text);
                    string txt = result.Text.Length > 10 ? $"长度为{result.Text.Length}" : result.Text;
                    context.WriteLog($"二维码识别结果{txt}");
                }
                else
                {
                    context.WriteLog($"二维码识别出错");
                }
            }
        }

        public static Bitmap toBitmap(BitMatrix matrix)
        {
            int width = matrix.Width;
            int height = matrix.Height;
            Bitmap bmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    bmap.SetPixel(x, y, matrix[x, y] ? ColorTranslator.FromHtml("0xFF000000") : ColorTranslator.FromHtml("0xFFFFFFFF"));
                }
            }
            return bmap;
        }

        public override void ShowConfig()
        {
            litsdk.API.ShowSystemConfigForm(this);
        }

        public override void Validate(ActivityContext context)
        {
            if (this.IsCreate)
            {
                if (string.IsNullOrEmpty(this.Content)) throw new Exception("生成二维码内容不得为空");
                if (string.IsNullOrEmpty(this.SaveVarName)) throw new Exception("保存变量不得为空");
                if (!context.ContainsStr(this.SaveVarName)) throw new Exception($"保存变量名{this.SaveVarName}不存在");
            }
            else
            {
                if (string.IsNullOrEmpty(this.Content)) throw new Exception("识别二维码图片地址不得为空");
                if (string.IsNullOrEmpty(this.SaveVarName)) throw new Exception("识别结果变量不得为空");
                if (!context.ContainsStr(this.SaveVarName)) throw new Exception($"识别结果变量名{this.SaveVarName}不存在");
            }
        }
    }
}
